﻿#region

using KandaAlpha.Domain.Model.Entities;
using KandaAlpha.Domain.Model.ValueObjects;
using KandaAlpha.Domain.Repository;
using KandaAlpha.Infrastructure.Interfaces.Geocoding;
using KandaAlpha.Infrastructure.Interfaces.Messaging;
using KandaAlpha.Application.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;

#endregion

namespace KandaAlpha.Application.Impl.Tests.Service
{
    /// <summary>
    ///
    /// Summary description for RegistrationServiceTest
    /// </summary>
    ///
    [TestClass]
    public class RegistrationServiceTest
    {
        private TestContext testContextInstance;

        public RegistrationServiceTest()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        /// <summary>
        ///
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        ///
        public TestContext TestContext
        {
            get { return testContextInstance; }
            set { testContextInstance = value; }
        }

        #region Additional test attributes

        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //

        #endregion

        [TestMethod]
        public void RegisterUser_Pass()
        {
            var mocks = new MockRepository();
            var messageSender = mocks.Stub<IMessageSender>();
            var userRepository = mocks.Stub<IUserRepository>();
            var addressGeocoder = mocks.Stub<IAddressGeocoder>();
            var unitOfWorkFactory = mocks.Stub<IUnitOfWorkFactory>();
            var repositoryContext = mocks.Stub<IRepositoryContext>(); 

            var registrationService =
                new RegistrationService(addressGeocoder,
                                        userRepository,
                                        messageSender, unitOfWorkFactory);

            var address = "1 Queen Street, Auckland City, Auckland, New Zealand";
            var user = new User
                           {
                               FirstName = "Will",
                               LastName = "Beattie",
                               Email = "beattie.w@gmail.com",
                               Address = address
                           };


            //let's set up the results
            using (mocks.Record())
            {
                SetupResult
                    .For(addressGeocoder.GetCoordinatesFrom(address))
                    .Return(new Coordinates {Latitude = 30.000, Longitude = 30.000});

                SetupResult
                    .For(messageSender.SendConfirmationMessage(user))
                    .Return(true);

                SetupResult
                    .For(unitOfWorkFactory.Create())
                    .Return(new UnitOfWork(repositoryContext));
                
            }


            var actual = registrationService.RegisterUser(user);

            Assert.IsTrue(actual);

            userRepository.AssertWasCalled(ur => ur.Add(user));
            addressGeocoder.AssertWasCalled(ag => ag.GetCoordinatesFrom(address));
            messageSender.AssertWasCalled(ms => ms.SendConfirmationMessage(user));
        }
    }
}